/******************************************************************************************************
Copyright (C) 2019 Mestrelab Research S.L. All rights reserved.

This file is part of the MNova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*****************************************************************************************************/

/*globals BaseConverter, NMRSpectrum, File, TextStream, settings, strings, Env, Str, Dir, mainWindow, MessageBox, qsTr, Application*/
/*jslint plusplus: true, indent: 4*/

function IntegralSeriesConverterCustom() {
	"use strict";

	BaseConverter.call(this);
	this.exportFileFilter = "1D Integral Series Custom (*.csv *.txt)";
	this.showDialog = true;
}

IntegralSeriesConverterCustom.prototype = new BaseConverter();

IntegralSeriesConverterCustom.prototype.wantsExport = function (aPageItems) {
	"use strict";

	var i, nmrSpc;

	for (i = 0; i < aPageItems.length; i++) {
		if (aPageItems[i].name === "NMR Spectrum") {
			nmrSpc = new NMRSpectrum(aPageItems[i]);
			if (nmrSpc.isValid()) {
				if (nmrSpc.dimCount === 1 && nmrSpc.integrals().count !== 0) {
					return true;
				}
			}
		}
	}

	return false;

};

IntegralSeriesConverterCustom.prototype.integralList = function (aNMRSpec, aReverse) {
	"use strict";

	var i, tempOldIntegral, tempIntegralValue, tempRangeMin, tempRangeMax, tempNormValue, tempIntegralNormValue, tempNewIntegral, OldIntegralList = aNMRSpec.integrals(), arrayOfIntegrals = [], newIntegralList;

	for (i = 0; i < OldIntegralList.count; i++) {
		tempOldIntegral = OldIntegralList.at(i);
		tempIntegralValue = tempOldIntegral.integralValue(1.0);
		tempRangeMax = tempOldIntegral.rangeMax(1);
		tempRangeMin = tempOldIntegral.rangeMin(1);
		tempNormValue = OldIntegralList.normValue;
		tempIntegralNormValue = tempOldIntegral.integralValue(tempNormValue);
		tempNewIntegral = {integralValue: tempIntegralValue, rangeMax: tempRangeMax, rangeMin: tempRangeMin, integralNormValue: tempIntegralNormValue, method: tempOldIntegral.calculationParams.method};
		arrayOfIntegrals.push(tempNewIntegral);
	}
	if (aReverse === false) {
		arrayOfIntegrals.sort(function (a, b) {return a.rangeMin - b.rangeMin; });
	}
	if (aReverse === true) {
		arrayOfIntegrals.sort(function (a, b) {return b.rangeMin - a.rangeMin; });
	}
	newIntegralList = {integrals: arrayOfIntegrals, normValue: OldIntegralList.normValue};

	return newIntegralList;

};

IntegralSeriesConverterCustom.prototype.writeHeader = function (aMaxNumInt, aHeader, aIndexFormat, aDataFormat) {
	"use strict";

	var header, i;

	header = aIndexFormat;
	header = header.replace(/\{/g, "");
	header = header.replace(/\}/g, "");
	for (i = 1; i <= aMaxNumInt; i++) {
		header += aDataFormat;
		header = header.replace(/\{/g, "");
		header = header.replace(/\}/g, "_" + i);
	}

	return header;

};

IntegralSeriesConverterCustom.prototype.writeIndex = function (aTitle, aCounter, aIndexFormat, aDataFormat, aMapObj, aIntegral) {
	"use strict";

	var i, separators;

	if (aIndexFormat !== undefined) {
		separators = aIndexFormat.match(/[^}]+(?![^{]*\})/gi);
	} else {
		separators = "";
	}
	if (aDataFormat !== undefined){
		separators.concat(aDataFormat.match(/[^}]+(?![^{]*\})/gi));
	} else {
		separators = "";
	}
	aMapObj.counter = aCounter;
	if (aTitle || aTitle !== "" ) {
		for (i = 0; i < separators.length; i++) {
			aTitle = aTitle.replace(/\n/g,"_");
			aTitle = Str.linifyAndQuote(aTitle, separators[i]);
		}
		aMapObj.title = aTitle;
	} else {
		aMapObj.title = " ";
	}
	if (aIntegral || aIntegral !== 0) {
		aMapObj.method = aIntegral.method;
	} else {
		aMapObj.method = " ";
	}

	return aIndexFormat.formatMap(aMapObj);

};

IntegralSeriesConverterCustom.prototype.writeSingleIntegral = function (aIndex, aIntegral, aNormValue, aDecimals, aDataFormat, aMapObj) {
	"use strict";

	var  range_min, range_max, abs_value, norm_value;

	range_min = aIntegral.rangeMin.toFixed(aDecimals);
	range_max = aIntegral.rangeMax.toFixed(aDecimals);
	abs_value = aIntegral.integralValue.toFixed(aDecimals);
	norm_value = aIntegral.integralNormValue.toFixed(aDecimals);
	aMapObj.range_min = range_min;
	aMapObj.range_max = range_max;
	aMapObj.abs_value = abs_value;
	aMapObj.norm_value = norm_value;

	return aDataFormat.formatMap(aMapObj);

};

IntegralSeriesConverterCustom.prototype.exportItems = function (aPageItems, aFilename) {
	"use strict";

	var dataColumnsFormat, dataColumnsFormats, indexColumnsFormat, indexColumnsFormats, dialog;

	dialog = Application.loadUiFile("ricares:WIntegralSeriesConverter.ui");
	dialog.widgets.cbHeader.checked = settings.value("IntegralSeriesConverterCustom/OutputHeader", dialog.widgets.cbHeader.checked);
	dialog.widgets.cbReverse.checked = settings.value("IntegralSeriesConverterCustom/Reverse", dialog.widgets.cbReverse.checked);
	dialog.widgets.cmbIndexColumnsFormat.items = settings.value("IntegralSeriesConverterCustom/IndexColumnsFormats", ["{counter}{tab}{title}{tab}", "{counter},{title},", "{title},", "{counter},"]).map(function (aItem) {return aItem.replace(/\[/g, "{").replace(/\]/g, "}"); });
	dialog.widgets.cmbDataColumnsFormat.items = settings.value("IntegralSeriesConverterCustom/DataColumnsFormats", ["{range_min}{tab}{range_max}{tab}{abs_value}{tab}{norm_value}{tab}", "{range_min},{range_max},{abs_value},{norm_value},", "{abs_value},"]).map(function (aItem) {return aItem.replace(/\[/g, "{").replace(/\]/g, "}"); });
	dialog.widgets.sbDecimalPlaces.value = settings.value("IntegralSeriesConverterCustom/DecimalsPlaces", dialog.widgets.sbDecimalPlaces.value);

	mainWindow.restoreCursor();

	if (this.showDialog === true) {
		if (!dialog.exec()) {
			return 0;
		}
	}

	settings.setValue("IntegralSeriesConverterCustom/OutputHeader", dialog.widgets.cbHeader.checked);
	settings.setValue("IntegralSeriesConverterCustom/Reverse", dialog.widgets.cbReverse.checked);

	indexColumnsFormat = dialog.widgets.cmbIndexColumnsFormat.currentText;
	indexColumnsFormats = dialog.widgets.cmbIndexColumnsFormat.items.filter(function (aElement, aIndex) {return aElement !== indexColumnsFormat && aIndex <= 8; });
	indexColumnsFormats.unshift(indexColumnsFormat);
	settings.setValue("IntegralSeriesConverterCustom/IndexColumnsFormats", indexColumnsFormats);

	dataColumnsFormat = dialog.widgets.cmbDataColumnsFormat.currentText;
	dataColumnsFormats = dialog.widgets.cmbDataColumnsFormat.items.filter(function (aElement, aIndex) {return aElement !== dataColumnsFormat && aIndex <= 8; });
	dataColumnsFormats.unshift(dataColumnsFormat);
	settings.setValue("IntegralSeriesConverterCustom/DataColumnsFormats", dataColumnsFormats);

	settings.setValue("IntegralSeriesConverterCustom/DecimalsPlaces", dialog.widgets.sbDecimalPlaces.value);

	mainWindow.setWaitCursor();

	try {
		this.formattedExport(aPageItems, aFilename, dialog.widgets.cbHeader.checked, dialog.widgets.cbReverse.checked, indexColumnsFormat.replace(/\{tab\}/g, "\t"), dataColumnsFormat.replace(/\{tab\}/g, "\t"), dialog.widgets.sbDecimalPlaces.value);
	} finally {
		mainWindow.restoreCursor();
	}
};

IntegralSeriesConverterCustom.prototype.formattedExport = function (aPageItems, aFilename, aHeader, aReverse, aIndexFormat, aDataFormat, aDecimals) {
	"use strict";

	var file, strm, i, spec, counter, originalSpcIndex, spcCount, integralList, j, integral, s, k, textIndexData, tempTextData, tempTextIndex, textHeader, maxNumInt = 0, mapObjData = {}, mapObjIndex = {};

	try {
		file = new File(aFilename);
		if (file.exists) {
			File.remove(aFilename);
		}
		if (file.open(File.WriteOnly)) {
			counter = 1;
			strm = new TextStream(file);
			textIndexData = "";
			for (i = 0; i < aPageItems.length; i++) {
				if (aPageItems[i].name === "NMR Spectrum") {
					spec = new NMRSpectrum(aPageItems[i]);
					if (spec.isValid() && spec.dimCount === 1) {
						originalSpcIndex = spec.curSpecIndex;
						spcCount = spec.specCount;
						for (s = 0; s < spcCount; s++) {
							spec.curSpecIndex = s;
							integralList = this.integralList(spec, aReverse);
							if (integralList.integrals.length) {
								if (integralList.integrals.length > maxNumInt) {
									maxNumInt = integralList.integrals.length;
								}
								for (j = 0; j < integralList.integrals.length; j++) {
									integral = integralList.integrals[j];
									if (j === 0) {
										tempTextIndex = this.writeIndex(Str.toOneWord(spec.formattedTitle), counter, aIndexFormat, aDataFormat, mapObjIndex, integral);
										textIndexData += tempTextIndex;
									}
									tempTextData = this.writeSingleIntegral(j, integral, integralList.normValue, aDecimals, aDataFormat, mapObjData);
									textIndexData += tempTextData;
								}
							} else {
								tempTextIndex = this.writeIndex(Str.toOneWord(spec.formattedTitle), counter, aIndexFormat, aDataFormat, mapObjIndex, 0);
								textIndexData += tempTextIndex;
							}
							counter++;
							textIndexData += "\r\n";
						}
						spec.curSpecIndex = originalSpcIndex;
					}
				}
			}
			if (aHeader) {
				textHeader = IntegralSeriesConverterCustom.prototype.writeHeader(maxNumInt, aHeader, aIndexFormat, aDataFormat);
				strm.write(textHeader);
				strm.write("\r\n");
			}
			strm.write(textIndexData);
			file.close();
		}
	} catch (e) {
		MessageBox.critical(qsTr("Exception found: {0}".format(e)));
	} finally {
		file.close();
	}
};

Env.Converters.push(new IntegralSeriesConverterCustom());

//--------------------------------------------------------------IntegralSeriesConverter---------------------------------------

function IntegralSeriesConverter() {
	"use strict";

	BaseConverter.call(this);
	this.exportFileFilter = "1D Integral Series (*.csv *.txt)";
	this.showDialog = false;
}

IntegralSeriesConverter.prototype = new IntegralSeriesConverterCustom();

Env.Converters.push(new IntegralSeriesConverter());

//----------------------------------------------------------MultipletsIntegralSeriesConverter-----------------------------------

function MultipletIntegralSeriesConverter() {
	"use strict";

	IntegralSeriesConverterCustom.call(this);
	this.exportFileFilter = "1D Multiplet Integral Series (*.csv *.txt)";
	this.showDialog = false;
}

MultipletIntegralSeriesConverter.prototype = new IntegralSeriesConverterCustom();

MultipletIntegralSeriesConverter.prototype.integralList = function (aNMRSpec, aReverse) {
	"use strict";
	var arrayOfIntegrals = [], i, OldIntegralList = aNMRSpec.multiplets(), tempIntegral, tempIntegralValue, tempRangeMax, tempRangeMin, tempNormValue, tempNewIntegral, tempIntegralNormValue, newIntegralList;

	for (i = 0; i < OldIntegralList.count; i++) {
		tempIntegral = OldIntegralList.at(i);
		tempIntegralValue = tempIntegral.integralValue(1.0);
		tempRangeMax = tempIntegral.rangeMax;
		tempRangeMin = tempIntegral.rangeMin;
		tempNormValue = OldIntegralList.normValue;
		tempIntegralNormValue = tempIntegral.integralValue(tempNormValue);
		tempNewIntegral = {integralValue: tempIntegralValue, rangeMax: tempRangeMax, rangeMin: tempRangeMin, integralNormValue: tempIntegralNormValue, method: tempIntegral.calculationParams.method};
		arrayOfIntegrals.push(tempNewIntegral);
	}
	if (aReverse === false) {
		arrayOfIntegrals.sort(function (a, b) {return a.rangeMin - b.rangeMin; });
	}
	if (aReverse === true) {
		arrayOfIntegrals.sort(function (a, b) {return b.rangeMin - a.rangeMin; });
	}
	newIntegralList = {integrals: arrayOfIntegrals, normValue: OldIntegralList.normValue};

	return newIntegralList;

};

MultipletIntegralSeriesConverter.prototype.wantsExport = function (aPageItems) {
	"use strict";

	var i, nmrSpc;
	for (i = 0; i < aPageItems.length; i++) {
		nmrSpc = new NMRSpectrum(aPageItems[i]);
		if (nmrSpc.isValid()) {
			return nmrSpc.multiplets().count > 0;
		}
	}

	return false;

};

MultipletIntegralSeriesConverter.prototype.writeSingleIntegral = function (aIndex, aIntegral, aNormValue, aDecimals, aDataFormat, aMapObj) {
	"use strict";

	var range_min, range_max, abs_value, norm_value;

	range_min = aIntegral.rangeMin.toFixed(aDecimals);
	range_max = aIntegral.rangeMax.toFixed(aDecimals);
	abs_value = aIntegral.integralValue.toFixed(aDecimals);
	norm_value = aIntegral.integralNormValue.toFixed(aDecimals);
	aMapObj.range_min = range_min;
	aMapObj.range_max = range_max;
	aMapObj.abs_value = abs_value;
	aMapObj.norm_value = norm_value;

	return aDataFormat.formatMap(aMapObj);

};

Env.Converters.push(new MultipletIntegralSeriesConverter());

